//------------------------------------------------------------------------------//          .
//		Instituto Tecnológico de Costa Rica       //        .  `.
//		IC-6400 Investigación de Operaciones   //      .  `.  `.
//										//    .  `.  `.  `v
//		Prof. Francisco J. Torres Rojas		      //  .  `.  `.  `v  `v
//										//.  `.  `.  `v  `v `V
//		Estudiantes:						// `.  `.  `v  `v  `V
//					Luis A. Cubillo Soto        //   `.  `v  `v  `V
//					200963696		       //       `v  `V
//					Leonel J. Murillo Retana //         `V
//					200900572		       // ____  _____ ____
// 										// |_   _| ____/  ___|
// 		III Proyecto: 						 //   |  |  |  _|   | |
// 				Transportes		        	//   |  |  | |__| |  ___
//------------------------------------------------------------------------------//   |_ | |_____\____|
#include "Structures.h"
#include "Global.h"
#include "Vogel.h"
#include "Matrix.h"
#include <stdlib.h>
#include <stdio.h>

int MIN_I, MIN_J;

int main(int argc, char** argv) {
    
    printf("hola mundo");


    Stones** leo;
    leo = (Stones**)malloc(80*sizeof(Stones*));
    int l;
    for (l = 0; l < 3; l++){
        leo[l] = (Stones*)malloc(80*sizeof(Stones));
    }
    
    
    LENGTH_COSTS = 12;
    PRODUCERS  = 3;
    MAX_PRODUCTION = (int*)malloc(3*sizeof(int));
    MAX_PRODUCTION[0] = 35;
    MAX_PRODUCTION[1] = 50;
    MAX_PRODUCTION[2] = 40;    
    CONSUMERS = 4;
    CONSUMER_NEEDS = (int*)malloc(4*sizeof(int));
    CONSUMER_NEEDS[0] = 45;
    CONSUMER_NEEDS[1] = 20;
    CONSUMER_NEEDS[2] = 30;
    CONSUMER_NEEDS[3] = 30;


    leo[0][0].transportation = 8;
    leo[0][1].transportation = 6;
    leo[0][2].transportation = 10;
    leo[0][3].transportation = 9;
   

    leo[1][0].transportation = 9;
    leo[1][1].transportation = 12;
    leo[1][2].transportation = 13;
    leo[1][3].transportation = 7;
   

    leo[2][0].transportation = 14;
    leo[2][1].transportation = 9;
    leo[2][2].transportation = 16;
    leo[2][3].transportation = 5;
   
    STONE = leo;
    vogel();    
    print_mat(3, 4, STONE);


/*
    int uno, dos, o;

    for (o = 0; o < 3; o++){
    uno = smaller_row(leo[o], -1, 4);
    dos = smaller_row(leo[o], uno, 4);
    printf("los menores de la fila %d son %d y %d\n", o, uno, dos);
    }

    for (o = 0; o < 4; o++){
    uno = smaller_col(leo, -1,3,o);
    dos = smaller_col(leo, uno, 3,o);
    printf("los menores de la columna %d son %d y %d\n", o, uno, dos);
    }
*/

/*
    rock oxygen;
    oxygen = calculate_penalties(leo, 12, 3, 4);

    printf("La entrada %d, %d es la que tiene el mayor penalty con %d\n", oxygen.row, oxygen.column, oxygen.penalty);
*/

    return (EXIT_SUCCESS);
 }

void vogel(){
    /*
     *  1-Calcular penalties
     *  2-Seleccionar la mayor
     *  3-Decidir si matar fila o columna
     *  4-Repetir
     */
    int aux_prod = PRODUCERS, aux_cons = CONSUMERS;
    rock vogel_rock;
    while ((aux_prod > 1) &&  (aux_cons > 1)){
        vogel_rock = calculate_penalties(STONE, LENGTH_COSTS,
                PRODUCERS, CONSUMERS);
        //Here is where I gotta decide whether to kill a row or a column
        int prod, consu;
        prod = MAX_PRODUCTION[vogel_rock.row];
        consu = CONSUMER_NEEDS[vogel_rock.column];
        if (prod < consu){
            //mato la fila
            set_stone(vogel_rock, prod);
            visit_row(STONE[vogel_rock.row], CONSUMERS);
        }
        else{
            //mato la columna.
            set_stone(vogel_rock, consu);
            visit_col(STONE, vogel_rock.column, PRODUCERS);
        }
    }
}
////loneleoneleoeleneo
void set_stone(rock param, int winner){
    MAX_PRODUCTION[param.row] -= winner;
    CONSUMER_NEEDS[param.column] -= winner;
    STONE[param.row][param.column].margin = winner;
    STONE[param.row][param.column].stone = 1;
}

rock calculate_penalties(Stones** matrix, int costs_length, int prod, int cons){
    int i, penalty, min1, min2, stop1, stop2, selected, aux;
    char selected_char;
    rock rock_selected;
    //para las filas el stop es LENGTH_COSTS / PRODUCERS
    //para las columnas es    LENGTH_COSTS / CONSUMERS

    //Going for rows
    stop1 = costs_length / cons;
    for (i = 0; i < stop1; i++){
        min1 = smaller_row(matrix[i], -1, cons);
        min2 = smaller_row(matrix[i], min1, cons);
        if (penalty < abs(min1 - min2)){
            penalty = abs(min1 - min2);
            selected = i;
            selected_char = 'r'; //as in row
        }
    }

    stop2 = costs_length / prod;
    //Going for columns
    for(i = 0; i < stop2; i++){
        min1 = smaller_col(matrix, -1, prod, i);
        min2 = smaller_col(matrix, min1, prod, i);
        if (penalty < abs(min1 - min2)){
            penalty = abs(min1 - min2);
            selected = i;
            selected_char = 'c';//as in column
        }
    }

    rock_selected.penalty = penalty;
    rock_selected.selected_char = selected_char;;
    aux = -1;
    if (selected_char == 'r'){
        rock_selected.row = selected;
        for (i = 0; i < stop2; i++){
             if (((matrix[selected][i].transportation<aux) ||
                    (aux == -1)) && (matrix[selected][i].visited ==0)){
                 rock_selected.column = i;
                 aux = matrix[selected][i].transportation;
             }
        }
    }
    else if (selected_char == 'c'){
        rock_selected.column = selected;
        for (i = 0; i < stop1; i++){
             if (((matrix[selected][i].transportation<aux) ||
                    (aux == -1)) && (matrix[selected][i].visited ==0)){
                 rock_selected.row = i;
                 aux =matrix[selected][i].transportation;
             }
        }
    }
    return rock_selected;
}

int smaller_row(Stones* array, int exception, int limit){
    int small = -1;
    int i;
    for (i = 0; i < limit; i++){
        //Exception is used when I already have one of the smaller numbers
        if ((array[i].transportation != exception) && (array[i].visited==0)){
            if ((array[i].transportation<small) || (small == -1)){
                small = array[i].transportation;
               // array[i].visited = 1;
            }
        }
    }
    return small;
}

int smaller_col(Stones** matrix, int exception, int limit, int column){
    int small = -1;
    int i;
    for (i = 0; i < limit; i++){
        if ((matrix[i][column].transportation != exception) &&
                (matrix[i][column].visited ==0) ){
            if ((matrix[i][column].transportation<small) ||
                    (small == -1)){
                small = matrix[i][column].transportation;
                //matrix[i][column].visited = 1;
            }
        }
    }
    return small;
}

void visit_row(Stones* array, int stop){
    int i;
    for (i = 0; i < stop; i++)
        array[i].visited = 1;
}

void visit_col(Stones** matrix, int column, int stop){
    int i;
    for(i = 0; i < stop; i++)
        matrix[i][column].visited = 1;
}